//
//  UnityCaptureConnection.m
//  UnityCapture
//
//  Created by Adrian on 29.10.09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "UnityCaptureConnection.h"

NSString *UCCaptureConnectionEstablishedNotification = @"UCCaptureConnectionEstablishedNotification";
NSString *UCStartCaptureNotification = @"UCStartCaptureNotification";
NSString *UCStopCaptureNotification = @"UCStopCaptureNotification";

@interface UnityCaptureConnection (PrivateMethods) <UCCoreProtocol>
- (void)openHelperAndConnect;
- (void)sendNotificationOnMainThread:(const NSString*)name;
- (void)loadSettingsFromHelper;
- (void)sendSize:(NSValue*)sizeValue;
- (void)sendStats:(NSArray*)stats;
- (void)sendHelperShouldOpenWindow;
- (void)sendToggleCapture;
- (void)helperConnectionDidClose;
@end

@implementation UnityCaptureConnection (PrivateMethods)

- (void)sendNotificationOnMainThread:(NSString*)name
{
	[[NSNotificationCenter defaultCenter] postNotificationName:name object:self];
}

- (void)openHelperAndConnect
{
	NSAutoreleasePool * pool = [NSAutoreleasePool new];
	
	// Open server connection
	serverConnection = [[NSConnection serviceConnectionWithName:@"UnityCaptureCore" rootObject:self] retain];
	
	// Open helper application
	NSBundle *pluginBundle = [NSBundle bundleWithIdentifier:@"ch.sttz.UnityCapture"];
	[[NSWorkspace sharedWorkspace] openFile:[pluginBundle pathForResource:@"UnityCaptureHelper" ofType:@"app"]];
	
	[[NSRunLoop currentRunLoop] run];
	[NSThread exit];
	
	[pool release];
}

- (void)helperServerHasStarted
{
	// Open client connection
	while (!clientConnection) {
		clientConnection = [[NSConnection connectionWithRegisteredName:@"UnityCaptureHelper" host:nil] retain];
		
		if (clientConnection)
			break;
		
		NSInteger reply = NSRunAlertPanel(
										  @"Connection Failed",
										  @"Connection to Unity Capture Helper couldn't be established.\nMake sure the Unity product is running and try again.",
										  @"Try again...",
										  @"Abort",
										  nil
										  );
		
		if (reply == NSAlertAlternateReturn) {
			//???
			return;
		}
	}
	[clientConnection retain];
	helperProxy = [[clientConnection rootProxy] retain];
	[helperProxy setProtocolForProxy:@protocol(UCHelperAppProtocol)];
	helperProto = (id <UCHelperAppProtocol>)helperProxy;
	
	// Watch connection
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(helperConnectionDidClose)
												 name:NSConnectionDidDieNotification
											   object:clientConnection];
	
	[self sendNotificationOnMainThread:UCCaptureConnectionEstablishedNotification];
	
	if (startWithOpenWindow)
		[helperProto openCaptureWindow];
}

- (void)startCapture
{
	[self performSelectorOnMainThread:@selector(sendNotificationOnMainThread:) 
						   withObject:UCStartCaptureNotification
						waitUntilDone:NO];
}

- (void)stopCapture
{
	[self performSelectorOnMainThread:@selector(sendNotificationOnMainThread:) 
						   withObject:UCStopCaptureNotification
						waitUntilDone:NO];
}

- (void)loadSettingsFromHelper
{
	NSString *outputPath = [helperProto outputPath];
	NSData *dataComponent = [helperProto compressionOptions];
	NSValue *resolution = [helperProto captureResolution];
	
	loadedData = [[NSArray alloc] initWithObjects:outputPath, dataComponent, resolution, nil];
}

- (void)sendSize:(NSValue*)sizeValue
{
	NSSize size = [sizeValue sizeValue];
	[helperProto newPlayerResolutionWithWidth:size.width andHeight:size.height];
}

- (void)sendStats:(NSArray*)stats
{
	[helperProto updateStatsWithFps:[[stats objectAtIndex:0] floatValue]
							andTime:[[stats objectAtIndex:1] floatValue]];
}

- (void)sendHelperShouldOpenWindow
{
	[helperProto openCaptureWindow];
}

- (void)sendToggleCapture
{
	[helperProto toggleCapture];
}

- (void)helperConnectionDidClose
{
	[clientConnection release];
	clientConnection = nil;
	[helperProxy release];
	helperProxy = nil;
	helperProto = nil;
}

@end


@implementation UnityCaptureConnection

- (id)init
{
	//Make sure client goes through designated initializer
	[self doesNotRecognizeSelector:_cmd];
	return nil;
}

- (id)initWithOpenWindow:(BOOL)open
{
	if (self = [super init]) {
		
		startWithOpenWindow = open;
		
		// Start seperate thread for connection
		thread = [[NSThread alloc] initWithTarget:self selector:@selector(openHelperAndConnect) object:nil];
		[thread start];
	}
	return self;
}

- (BOOL)connectionIsValid
{
	return [clientConnection isValid];
}

- (NSArray*)loadSettings
{
	// Load settings through NSConnection on other thread
	[self performSelector:@selector(loadSettingsFromHelper)
				 onThread:thread
				withObject:nil
			waitUntilDone:YES];
	
	return [loadedData autorelease];
}

- (void)sendStatsWithFps:(float)fps andTime:(float)time
{
	NSArray *stats = [NSArray arrayWithObjects:
					  [NSNumber numberWithFloat:fps],
					  [NSNumber numberWithFloat:time],
					  nil];
	
	[self performSelector:@selector(sendStats:)
				 onThread:thread
			   withObject:stats
			waitUntilDone:NO];
}

- (void)openHelper
{
	[self performSelector:@selector(sendHelperShouldOpenWindow)
				 onThread:thread
			   withObject:nil
			waitUntilDone:NO];
}

- (void)toggleCapture
{
	[self performSelector:@selector(sendToggleCapture)
				 onThread:thread
			   withObject:nil
			waitUntilDone:NO];
}

- (void)sendNewResolutionWithWidth:(float)width andHeight:(float)height
{
	[self performSelector:@selector(sendSize:)
				 onThread:thread
			   withObject:[NSValue valueWithSize:NSMakeSize(width, height)]
			waitUntilDone:NO];
}

- (void)dealloc
{
	[self helperConnectionDidClose];
	
	[super dealloc];
}

@end
